Add repository-level vulnerability summary to vulnerabilities command#282
Add repository-level vulnerability summary to vulnerabilities command#282colinmoynes wants to merge 18 commits intomasterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR expands the CLI’s vulnerability reporting to support repository-level aggregation, and also introduces download-command enhancements (filename filtering and multi-package downloads), along with associated version/dependency bumps.
Changes:
- Add
cloudsmith vulnerabilities OWNER/REPOmode to aggregate vulnerability counts across all packages in a repository (with filtering and JSON output). - Enhance
cloudsmith downloadwith--filenamefiltering (including glob patterns) and--download-all, plus improved multi-match display. - Bump CLI version metadata to
1.16.0and updatecloudsmith-apidependency to2.0.25.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
cloudsmith_cli/cli/commands/vulnerabilities.py |
Adds repo-level summary mode, aggregation/filtering, and rich table output. |
cloudsmith_cli/core/api/vulnerabilities.py |
Updates summary table rendering and adjusts scan identifier handling. |
cloudsmith_cli/cli/validators.py |
Adds validator to accept OWNER/REPO[/SLUG_PERM] for vulnerabilities command arg. |
cloudsmith_cli/core/download.py |
Adds filename filtering (server/client side) and refactors multi-match output via rich table; adds resolve-all helper. |
cloudsmith_cli/cli/commands/download.py |
Adds --filename and --download-all, refactors download flow, and adds safe path joining. |
cloudsmith_cli/core/tests/test_download.py |
Adds unit tests for filename filtering, resolve-all behavior, and multi-match display. |
cloudsmith_cli/cli/tests/commands/test_download.py |
Adds integration-style CLI tests for new download flags/behavior. |
cloudsmith_cli/cli/commands/upstream.py |
Adds alpine to supported upstream formats list. |
README.md |
Documents new download flags (--filename, --download-all). |
CHANGELOG.md |
Adds entries for new features/releases (but currently with duplicated 1.14.0 sections). |
setup.py / requirements.txt |
Bumps cloudsmith-api dependency from 2.0.24 to 2.0.25. |
cloudsmith_cli/data/VERSION / .bumpversion.cfg |
Bumps version to 1.16.0. |
Comments suppressed due to low confidence (2)
CHANGELOG.md:60
- The changelog now contains two separate
## [1.14.0]sections (with different dates), which makes it ambiguous which entry is authoritative. Consider consolidating these into a single1.14.0section (or correcting the version/date as appropriate).
## [1.14.0] - 2026-03-11
### Added
- Added `vulnerabilities` command to retrieve security scan results for a package
- Summary View (Default): Displays a high-level count of vulnerabilities broken down by severity (Critical, High, Medium, Low, Unknown).
- Assessment View `--show-assessment` (`-A`): Provides a detailed breakdown where vulnerabilities are:
- Grouped by the specific affected upstream package / dependency.
- Sorted by severity (Critical first).
- Richly formatted tables.
- Filtering Capabilities:
- By Severity: `--severity` Show only specific levels (e.g., just Critical and High).
- By Status: `--fixable | --non-fixable` Filter to show only "Fixable" vulnerabilities (where a patch exists) or "Non-Fixable" ones.
- Supports `--output-format json | pretty_json` for programmatic usage
## [1.14.0] - 2026-03-13
### Added
- Added `vulnerabilities` command to retrieve security scan results for a package
- Summary View (Default): Displays a high-level count of vulnerabilities broken down by severity (Critical, High, Medium, Low, Unknown).
- Assessment View `--show-assessment` (`-A`): Provides a detailed breakdown where vulnerabilities are:
- Grouped by the specific affected upstream package / dependency.
- Sorted by severity (Critical first).
- Richly formatted tables.
- Filtering Capabilities:
CHANGELOG.md:23
cloudsmith_cli/data/VERSIONand.bumpversion.cfgare bumped to1.16.0, but the new vulnerability summary entry is still under[Unreleased]rather than the1.16.0release section. If this change is part of 1.16.0, consider moving it into the## [1.16.0]section; otherwise consider not bumping the version yet.
## [Unreleased]
### Added
- Added repository-level vulnerability summary (`cloudsmith vulnerabilities OWNER/REPO`)
- Aggregates scan results across all packages into a single color-coded table
- Packages sorted by total vulnerability count (descending)
- Packages without scan results are silently omitted
- Supports `--severity` and `--fixable/--non-fixable` filters
## [1.16.0] - 2026-03-24
### Added
- Added Alpine Upstream support for managing upstream configurations.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
842b05e to
df3070c
Compare
…now for single packages
df3070c to
0f5ee19
Compare
da15095 to
b6ef8cd
Compare
…bility-summary-for
… status including "Security scan not supported" and "No issues found" to match the UI.
…ndling and results handling.
| def get_packages_in_repo(opts, owner, repo): | ||
| """Get all packages in a repository, paginating through all pages.""" | ||
| all_packages = [] | ||
| page = 1 | ||
| page_size = 100 # fetch in larger batches for efficiency | ||
|
|
||
| try: | ||
| while True: | ||
| packages, page_info = list_packages( | ||
| opts=opts, | ||
| owner=owner, | ||
| repo=repo, | ||
| query=None, | ||
| sort=None, | ||
| page=page, | ||
| page_size=page_size, | ||
| ) | ||
|
|
||
| if packages: | ||
| all_packages.extend(packages) | ||
|
|
||
| # No page info means single page or no results | ||
| if not page_info: | ||
| break | ||
|
|
||
| current_page = getattr(page_info, "page", page) | ||
| total_pages = getattr(page_info, "page_total", 1) | ||
|
|
||
| if current_page >= total_pages: | ||
| break | ||
|
|
||
| page += 1 | ||
|
|
||
| except Exception as exc: | ||
| raise click.ClickException( | ||
| f"Failed to list packages for '{owner}/{repo}'. " | ||
| f"Please check the owner and repository names are correct. " | ||
| f"Detail: {exc}" | ||
| ) from exc | ||
|
|
||
| if not all_packages: | ||
| raise click.ClickException( | ||
| f"No packages found in '{owner}/{repo}'. " | ||
| f"The repository may be empty, or the owner/repo names may be incorrect." | ||
| ) | ||
|
|
||
| return [ | ||
| (pkg["slug_perm"], pkg.get("name", pkg["slug_perm"]), pkg.get("version", "")) | ||
| for pkg in all_packages | ||
| ] |
There was a problem hiding this comment.
question: why do you need a new function for this instead of doing the same as here? https://github.com/cloudsmith-io/cloudsmith-cli/blob/master/cloudsmith_cli/cli/commands/list_.py#L221
Also if there's a lot of packages this will take A WHILE
| # click.echo( | ||
| # f"No vulnerability scan results found for package: {package}", err=True | ||
| # ) | ||
| return None |
There was a problem hiding this comment.
change: if you don't need the echo here anymore remove the comment
| slugs = get_packages_in_repo(opts, owner, repo) | ||
|
|
||
| repo_summary_rows = _collect_repo_scan_data( | ||
| opts, owner, repo, slugs, severity_filter, fixable | ||
| ) |
There was a problem hiding this comment.
nit: you should test this out with a repo with a high count of packages, got the feeling it will take a very long time to gather all the data you need. A server-side component might be needed
This pull request introduces improvements to the vulnerability command. It adds a repository-level vulnerability summary capability, allowing users to aggregate and filter vulnerability data across all packages in a repository.
Type of Change
Additional Notes